[AWS CDK] スナップショットテストのシリアライザーで複数種類の置換処理を行う

[AWS CDK] スナップショットテストのシリアライザーで複数種類の置換処理を行う

Clock Icon2024.6.18

こんにちは、製造ビジネステクノロジー部の若槻です。

AWS CDKのスナップショットテストでは、シリアライザー(Serializer)を使ってスナップショットファイルに出力される内容をカスタマイズすることができます。

それによりハッシュ値などのデプロイ時に意図せず変わりうる値をダミー値に置き換えることができ、スナップショットテストの安定性を向上させることができます。

今回は、AWS CDK のスナップショットテストのシリアライザーで複数種類の置換処理を行う方法を確認してみました。

結論

結論としては、プラグインオブジェクトのシリアライザー処理を下記のように設定することで、置換処理を複数種類行うことができます。

export const serializer = {
  test: (val: unknown) => typeof val === 'string',
  serialize: (val: string) => {
    return `"${val
      // Asset hash をダミー値に置き換え
      .replace(/([A-Fa-f0-9]{64}.zip)/, 'HASH_REPLACED.zip')
      // Construct address をダミー値に置き換え
      .replace(/[a-f0-9]{42}/, '[CONSTRUCT_ADDR_REPLACED]')}"`;
  },
};

Asset hash(アセットハッシュ)は Lambda 関数のアーカイブファイル(zip)に対して付与されるハッシュ値で、ソースコードが変更されるとハッシュ値も変わります。

Construct address は CDK リソースを一意に識別するための英数字 42 桁のアドレスで、スタック名など上位の Construct パスが変更されると変わります。

動作確認

環境

$ npm ls vitest aws-cdk@  
cdk_sample_app@0.1.0 /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/cdk_sample_app
├── aws-cdk@2.145.0
└── vitest@1.6.0

CDK で既定で導入されるテスティングフレームワークは Jest ですが、今回は Vitest を使用しています。Jest と同様に Vitest もスナップショットテストに対応しています。

CDK スタック

テスト対象の CDK スタックです。合成後の情報として Asset Hash と Construct address を含む Lambda 関数を定義しています。

import { aws_lambda_nodejs, aws_lambda, Stack } from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class CdkSampleStack extends Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    new aws_lambda_nodejs.NodejsFunction(this, 'SampleFunc', {
      functionName: `SampleFunc-${this.node.addr}`,
      runtime: aws_lambda.Runtime.NODEJS_20_X,
    });
  }
}

テストコード

スナップショットテストのコードです。addSnapshotSerializer でシリアライザーのプラグインを追加しています。

import { test, expect } from 'vitest';
import * as cdk from 'aws-cdk-lib';
import { Template } from 'aws-cdk-lib/assertions';
import { serializer } from './snapshot-plugin';

import { CdkSampleStack } from '../lib/cdk-sample-stack';

test('Snapshot test', () => {
  const app = new cdk.App();

  const stack = new CdkSampleStack(app, 'CdkSampleStack');

  const template = Template.fromStack(stack);

  expect.addSnapshotSerializer(serializer); // シリアライザーを追加
  expect(template).toMatchSnapshot();
});

テスト実行

Vitest でスナップショットを生成します。

npx vitest ./test --run -u

すると Lambda 関数リソースの Asset hash と Construct address がダミー値に置き換わったスナップショットファイルが生成されました!

// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`Snapshot test 1`] = `
{
  "Parameters": {
    "BootstrapVersion": {
      "Default": "/cdk-bootstrap/hnb659fds/version",
      "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]",
      "Type": "AWS::SSM::Parameter::Value<String>",
    },
  },
  "Resources": {
    "SampleFunc1AE55385": {
      "DependsOn": [
        "SampleFuncServiceRole6ADD7EC2",
      ],
      "Properties": {
        "Code": {
          "S3Bucket": {
            "Fn::Sub": "cdk-hnb659fds-assets-\${AWS::AccountId}-\${AWS::Region}",
          },
          "S3Key": "HASH_REPLACED.zip",
        },
        "FunctionName": "SampleFunc-[CONSTRUCT_ADDR_REPLACED]",
        "Handler": "index.handler",
        "Role": {
          "Fn::GetAtt": [
            "SampleFuncServiceRole6ADD7EC2",
            "Arn",
          ],
        },
        "Runtime": "nodejs20.x",
      },
      "Type": "AWS::Lambda::Function",
    },
    "SampleFuncServiceRole6ADD7EC2": {
      "Properties": {
        "AssumeRolePolicyDocument": {
          "Statement": [
            {
              "Action": "sts:AssumeRole",
              "Effect": "Allow",
              "Principal": {
                "Service": "lambda.amazonaws.com",
              },
            },
          ],
          "Version": "2012-10-17",
        },
        "ManagedPolicyArns": [
          {
            "Fn::Join": [
              "",
              [
                "arn:",
                {
                  "Ref": "AWS::Partition",
                },
                ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
              ],
            ],
          },
        ],
      },
      "Type": "AWS::IAM::Role",
    },
  },
  "Rules": {
    "CheckBootstrapVersion": {
      "Assertions": [
        {
          "Assert": {
            "Fn::Not": [
              {
                "Fn::Contains": [
                  [
                    "1",
                    "2",
                    "3",
                    "4",
                    "5",
                  ],
                  {
                    "Ref": "BootstrapVersion",
                  },
                ],
              },
            ],
          },
          "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI.",
        },
      ],
    },
  },
}
`;

おわりに

AWS CDK のスナップショットテストのシリアライザーを使って、スナップショットファイルに出力される内容に対して複数の置換処理を行う方法を確認しました。

必要となる場面はあまり無いかも知れませんが、どなかたの参考になれば幸いです。

参考

以上

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.